package cn.com.easy.pay.alipay.www.controller;

import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;

import cn.com.easy.exception.BusinessException;
import cn.com.easy.pay.alipay.www.config.AlipayConfig;
import cn.com.easy.pay.alipay.www.util.AlipayNotify;

/**
 * 有密批量退款 基础控制器(spring mvc)
 * 
 * @author nibili 2017年4月1日
 * 
 */
public abstract class AlipayRefundNotifyBaseController {

	private Logger logger = LoggerFactory.getLogger(AlipayRefundNotifyBaseController.class);

	/**
	 * 阿里配置参数
	 * 
	 * @return
	 * @author nibili 2017年4月1日
	 */
	public abstract AlipayConfig getAlipayConfig() throws BusinessException;

	/**
	 * 支付宝有密批量退款完成， 异步回调，业务回调方法<br/>
	 * 不要做异常处理，让控制器来做，控制器可以把结果返回给支付宝<br/>
	 * 
	 * @param notifyParam
	 * @author nibili 2017年4月1日
	 */
	public abstract void notifyCallback(RefundNotifyParam notifyParam) throws BusinessException;

	/**
	 * 功能：支付宝服务器异步通知页面 版本：3.3 日期：2012-08-17 说明：
	 * 以下代码只是为了方便商户测试而提供的样例代码，商户可以根据自己网站的需要，按照技术文档编写,并非一定要使用该代码。
	 * 该代码仅供学习和研究支付宝接口使用，只是提供一个参考。
	 * 
	 * //***********页面功能说明*********** 创建该页面文件时，请留心该页面文件中无任何HTML代码及空格。
	 * 该页面不能在本机电脑测试，请到服务器上做测试。请确保外部可以访问该页面。
	 * 该页面调试工具请使用写文本函数logResult，该函数在com.alipay.util文件夹的AlipayCore.java类文件中
	 * 如果没有收到该页面返回的 success 信息，支付宝会在24小时内按一定的时间策略重发通知
	 * 
	 * @param request
	 * @param response
	 * @param notifyParam
	 * @author nibili 2017年4月1日
	 */
	@SuppressWarnings("unchecked")
	@RequestMapping("/notify")
	public void notify(HttpServletRequest request, HttpServletResponse response, RefundNotifyParam notifyParam) {
		try {
			// 获取支付宝POST过来反馈信息
			Map<String, String> params = new HashMap<String, String>();
			Map<String, String[]> requestParams = request.getParameterMap();
			for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
				String name = (String) iter.next();
				String[] values = (String[]) requestParams.get(name);
				String valueStr = "";
				for (int i = 0; i < values.length; i++) {
					valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
				}
				// 乱码解决，这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
				// valueStr = new String(valueStr.getBytes("ISO-8859-1"),
				// "gbk");
				params.put(name, valueStr);
			}
			// 获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//

			if (AlipayNotify.verify(params, getAlipayConfig())) {// 验证成功
				// ////////////////////////////////////////////////////////////////////////////////////////
				// 请在这里加上商户的业务逻辑程序代码

				// ——请根据您的业务逻辑来编写程序（以下代码仅作参考）——

				// 判断是否在商户网站中已经做过了这次通知返回的处理
				// 如果没有做过处理，那么执行商户的业务程序
				// 如果有做过处理，那么不执行商户的业务程序
				notifyCallback(notifyParam);
				response.getOutputStream().print("success"); // 请不要修改或删除

				// ——请根据您的业务逻辑来编写程序（以上代码仅作参考）——

				// ////////////////////////////////////////////////////////////////////////////////////////
			} else {// 验证失败
				throw new BusinessException("支付宝退款验证失败");
			}
		} catch (BusinessException ex) {
			try {
				response.getOutputStream().print("fail");
			} catch (IOException e) {
				e.printStackTrace();
			}
			logger.info("支付宝有密退款nofity业务代码异常", ex);
		} catch (Exception ex) {
			try {
				response.getOutputStream().print("fail");
			} catch (IOException e) {
				e.printStackTrace();
			}
			logger.info("支付宝有密退款nofity异常", ex);
		}
	}

	/**
	 * 支付宝 退款 异步回调返回的参数<br/>
	 * 详参：https://doc.open.alipay.com/docs/doc.htm?spm=a219a.7629140.0.0.KNgYXT&
	 * treeId=62&articleId=104744&docType=1#s1
	 * 
	 * @author nibili 2017年4月1日
	 * 
	 */
	public static class RefundNotifyParam {
		/* ===================基本参数================== */

		/** 通知时间 */
		private String notify_time;
		/** 通知类型 */
		private String notify_type;
		/** 通知校验ID */
		private String notify_id;
		/** 签名方式 */
		private String sign_type;
		/** 签名 */
		private String sign;

		/* =====================业务参数===================== */
		/** 退款批次号 */
		private String batch_no;
		/** 退款成功总数 */
		private String success_num;
		/** 退款结果明细 */
		private String result_details;

		/**
		 * get ========
		 * 
		 * @return
		 * @author nibili 2017年4月1日
		 */
		public String getNotify_time() {
			return notify_time;
		}

		/**
		 * set ========
		 * 
		 * @param notify_time
		 * @author nibili 2017年4月1日
		 */
		public void setNotify_time(String notify_time) {
			this.notify_time = notify_time;
		}

		/**
		 * get 通知类型
		 * 
		 * @return
		 * @author nibili 2017年4月1日
		 */
		public String getNotify_type() {
			return notify_type;
		}

		/**
		 * set 通知类型
		 * 
		 * @param notify_type
		 * @author nibili 2017年4月1日
		 */
		public void setNotify_type(String notify_type) {
			this.notify_type = notify_type;
		}

		/**
		 * get 通知校验ID
		 * 
		 * @return
		 * @author nibili 2017年4月1日
		 */
		public String getNotify_id() {
			return notify_id;
		}

		/**
		 * set 通知校验ID
		 * 
		 * @param notify_id
		 * @author nibili 2017年4月1日
		 */
		public void setNotify_id(String notify_id) {
			this.notify_id = notify_id;
		}

		/**
		 * get 签名方式
		 * 
		 * @return
		 * @author nibili 2017年4月1日
		 */
		public String getSign_type() {
			return sign_type;
		}

		/**
		 * set 签名方式
		 * 
		 * @param sign_type
		 * @author nibili 2017年4月1日
		 */
		public void setSign_type(String sign_type) {
			this.sign_type = sign_type;
		}

		/**
		 * get 签名
		 * 
		 * @return
		 * @author nibili 2017年4月1日
		 */
		public String getSign() {
			return sign;
		}

		/**
		 * set 签名
		 * 
		 * @param sign
		 * @author nibili 2017年4月1日
		 */
		public void setSign(String sign) {
			this.sign = sign;
		}

		/**
		 * get =========
		 * 
		 * @return
		 * @author nibili 2017年4月1日
		 */
		public String getBatch_no() {
			return batch_no;
		}

		/**
		 * set =========
		 * 
		 * @param batch_no
		 * @author nibili 2017年4月1日
		 */
		public void setBatch_no(String batch_no) {
			this.batch_no = batch_no;
		}

		/**
		 * get 退款成功总数
		 * 
		 * @return
		 * @author nibili 2017年4月1日
		 */
		public String getSuccess_num() {
			return success_num;
		}

		/**
		 * set 退款成功总数
		 * 
		 * @param success_num
		 * @author nibili 2017年4月1日
		 */
		public void setSuccess_num(String success_num) {
			this.success_num = success_num;
		}

		/**
		 * get 退款结果明细
		 * 
		 * @return
		 * @author nibili 2017年4月1日
		 */
		public String getResult_details() {
			return result_details;
		}

		/**
		 * set 退款结果明细
		 * 
		 * @param result_details
		 * @author nibili 2017年4月1日
		 */
		public void setResult_details(String result_details) {
			this.result_details = result_details;
		}

	}
}
